"""

Copyright MUAMP 2021 MUAMP.COM David French

This Circuit Python code to control the Robot Quadruped "PICO Python Dog" can be freely used and modified, providing:

This code must NOT be used for commercial use or for profit.

This comment must remain in the code at the top of the .py file and this comment must NOT be modified or removed.

"""


import time

import board

import busio

import pwmio

from adafruit_motor import servo

import adafruit_icm20x

from math import asin, acos, atan, degrees, sqrt

import pulseio

import adafruit_irremote



# IR sensor

IR_PIN = board.GP9 # Pin GP9 connected to IR receiver

# IR decoder

pulsein = pulseio.PulseIn(IR_PIN, maxlen=100, idle_state=True)

decoder = adafruit_irremote.GenericDecode()

pulsein.clear()

pulsein.resume()


# Acc Gyro Mag test setup on i2c (1)

i2c = busio.I2C(board.GP11, board.GP10)

icm = adafruit_icm20x.ICM20948(i2c)


# AGM functions

def Acc(): # Acc +/- 10 for 90 degrees of x and y axis (wobble board +...)

Ax = round(icm.acceleration[0]) # Gyro detects sudden movement in real time (compliance +...)

Ay = round(icm.acceleration[1]) # Mag (compass) for up side down detection

return Ax, Ay


# Servo setup (Raspberry Pi PICO micro controller (Circuit Python) with Tower Pro MG90S servos

FL_knee = servo.Servo(pwmio.PWMOut(board.GP0, duty_cycle=0, frequency=50), min_pulse=500, max_pulse=2400)

FL_hip = servo.Servo(pwmio.PWMOut(board.GP1, duty_cycle=0, frequency=50), min_pulse=500, max_pulse=2400)

FR_knee = servo.Servo(pwmio.PWMOut(board.GP27, duty_cycle=0, frequency=50), min_pulse=500, max_pulse=2400)

FR_hip = servo.Servo(pwmio.PWMOut(board.GP26, duty_cycle=0, frequency=50), min_pulse=500, max_pulse=2400)

BL_knee = servo.Servo(pwmio.PWMOut(board.GP14, duty_cycle=0, frequency=50), min_pulse=500, max_pulse=2400)

BL_hip = servo.Servo(pwmio.PWMOut(board.GP15, duty_cycle=0, frequency=50), min_pulse=500, max_pulse=2400)

BR_knee = servo.Servo(pwmio.PWMOut(board.GP21, duty_cycle=0, frequency=50), min_pulse=500, max_pulse=2400)

BR_hip = servo.Servo(pwmio.PWMOut(board.GP20, duty_cycle=0, frequency=50), min_pulse=500, max_pulse=2400)


# servo function - converts Cartesian inputs to degrees of angles of servos

def leg_control(FLx,FLy,FRx,FRy,BLx,BLy,BRx,BRy):


FRcal = -5 # calibration factor


FLhip, FLknee = rec2pol(FLx, FLy) # This IK code is interpolated by default!

FRhip, FRknee = rec2pol(FRx, FRy)

BLhip, BLknee = rec2pol(BLx, BLy)

BRhip, BRknee = rec2pol(BRx, BRy)


# degrees do NOT have to be integers

FL_knee.angle = 180 - FLknee

FL_hip.angle = 180 - FLhip

FR_knee.angle = FRknee + FRcal

FR_hip.angle = FRhip

BL_knee.angle = 180 - BLknee

BL_hip.angle = 180 - BLhip

BR_knee.angle = BRknee

BR_hip.angle = BRhip



def rec2pol(x,y): # upper and lower leg are both 50mm

hypotenuse = sqrt(y**2+x**2)

hip = 90+(degrees((atan(x/y))-acos(((hypotenuse**2)/(100*hypotenuse)))))

knee = degrees(acos(1-((hypotenuse**2)/5000)))

return hip, knee



def numbers(start, finish): # list of numbers from 'start' to 'finish' for smooth linear leg movement

numbers = []

if start < finish:

for new_number in range(start, finish, 1):

for fraction in range(0, 10, 2):

value = new_number + fraction/10

numbers.append(value)

else:

for new_number in range(start-1, finish-1, -1):

for fraction in range(10, 0, -2):

value = new_number + fraction/10

numbers.append(value)

numbers.append(finish+0.0)

return numbers



""" MAIN CODE """



time.sleep(3)



# EXERCISES

# STARTS AT LAY POSITION

# leg_control(FLx, FLy, FRx, FRy, BLx, BLy, BRx, BRy)

delay = 0.002


x = numbers(20, 80) # from lay position to walk position

for c in range(0, len(x)):

leg_control(0, x[c], 0, x[c], 0, x[c], 0, x[c])

time.sleep(delay)

time.sleep(1)



x = numbers(80, 10) # from walk position to lay position

for c in range(0, len(x)):

leg_control(0, x[c], 0, x[c], 0, x[c], 0, x[c])

time.sleep(delay)

time.sleep(1)



x = numbers(10, 70) # from lay to walk position

for c in range(0, len(x)):

leg_control(0, x[c], 0, x[c], 0, x[c], 0, x[c])

time.sleep(delay)

time.sleep(1)



x = numbers(0, -20) # from walk to slew forward

for c in range(0, len(x)):

leg_control(x[c], 70, x[c], 70, x[c], 70, x[c], 70) # wrt foot under hip

time.sleep(delay)

time.sleep(1)



x = numbers(-20, 10) # from slew forward to slew back

for c in range(0, len(x)):

leg_control(x[c], 70, x[c], 70, x[c], 70, x[c], 70) # -ve to +ve wrt foot under hip

time.sleep(delay)

time.sleep(1)



x = numbers(10, 0) # from slew forward to walk position

for c in range(0, len(x)):

leg_control(x[c], 70, x[c], 70, x[c], 70, x[c], 70) # and not the direction of the body

time.sleep(delay)

time.sleep(1)



x = numbers(70, 60) # from walk to lower walk

for c in range(0, len(x)):

leg_control(0, x[c], 0, x[c], 0, x[c], 0, x[c])

time.sleep(delay)

time.sleep(1)



x = numbers(60, 51) # from walk to roll left

for c in range(0, len(x)):

leg_control(0, x[c], 0, 60, 0, x[c], 0, 60)

time.sleep(delay*2.5)

time.sleep(1)



x = numbers(51, 60) # from roll left to roll right

for c in range(0, len(x)):

leg_control(0, x[c], 0, 60, 0, x[c], 0, 60)

time.sleep(delay*2.5)

x = numbers(60, 51) # from walk to roll left

for c in range(0, len(x)):

leg_control(0, 60, 0, x[c], 0, 60, 0, x[c])

time.sleep(delay*2.5)

time.sleep(1)



x = numbers(51, 60) # from roll left to walk position

for c in range(0, len(x)):

leg_control(0, 60, 0, x[c], 0, 60, 0, x[c])

time.sleep(delay*2.5)

time.sleep(1)



x = numbers(60, 20) # from walk position to lay position

for c in range(0, len(x)):

leg_control(0, x[c], 0, x[c], 0, x[c], 0, x[c])

time.sleep(delay)

time.sleep(1)



time.sleep(3)




# CRAWL

# leg_control(FLx, FLy, FRx, FRy, BLx, BLy, BRx, BRy)


delay = 0.002


while True:

leg_control(-40, 60, 40, 60, 40, 60, -40, 60)

time.sleep(delay)

leg_control(-39, 59.4, 39, 60, 39, 60, -39, 59.4)

time.sleep(delay)

leg_control(-38, 58.6, 38, 60, 38, 60, -38, 58.6)

time.sleep(delay)

leg_control(-37, 57.8, 37, 60, 37, 60, -37, 57.8)

time.sleep(delay)

leg_control(-36, 57, 36, 60, 36, 60, -36, 57)

time.sleep(delay)

leg_control(-35, 56.3, 35, 60, 35, 60, -35, 56.3)

time.sleep(delay)

leg_control(-34, 55.6, 34, 60, 34, 60, -34, 55.6)

time.sleep(delay)

leg_control(-33, 54.9, 33, 60, 33, 60, -33, 54.9)

time.sleep(delay)

leg_control(-32, 54.2, 32, 60, 32, 60, -32, 54.2)

time.sleep(delay)

leg_control(-31, 53.6, 31, 60, 31, 60, -31, 53.6)

time.sleep(delay)

leg_control(-30, 53, 30, 60, 30, 60, -30, 53)

time.sleep(delay)

leg_control(-29, 52.5, 29, 60, 29, 60, -29, 52.5)

time.sleep(delay)

leg_control(-28, 51.9, 28, 60, 28, 60, -28, 51.9)

time.sleep(delay)

leg_control(-27, 51.4, 27, 60, 27, 60, -27, 51.4)

time.sleep(delay)

leg_control(-26, 50.9, 26, 60, 26, 60, -26, 50.9)

time.sleep(delay)

leg_control(-25, 50.5, 25, 60, 25, 60, -25, 50.5)

time.sleep(delay)

leg_control(-24, 50, 24, 60, 24, 60, -24, 50)

time.sleep(delay)

leg_control(-23, 49.6, 23, 60, 23, 60, -23, 49.6)

time.sleep(delay)

leg_control(-22, 49.2, 22, 60, 22, 60, -22, 49.2)

time.sleep(delay)

leg_control(-21, 48.8, 21, 60, 21, 60, -21, 48.8)

time.sleep(delay)

leg_control(-20, 48.4, 20, 60, 20, 60, -20, 48.4)

time.sleep(delay)

leg_control(-19, 48.1, 19, 60, 19, 60, -19, 48.1)

time.sleep(delay)

leg_control(-18, 47.8, 18, 60, 18, 60, -18, 47.8)

time.sleep(delay)

leg_control(-17, 47.5, 17, 60, 17, 60, -17, 47.5)

time.sleep(delay)

leg_control(-16, 47.2, 16, 60, 16, 60, -16, 47.2)

time.sleep(delay)

leg_control(-15, 46.9, 15, 60, 15, 60, -15, 46.9)

time.sleep(delay)

leg_control(-14, 46.7, 14, 60, 14, 60, -14, 46.7)

time.sleep(delay)

leg_control(-13, 46.4, 13, 60, 13, 60, -13, 46.4)

time.sleep(delay)

leg_control(-12, 46.2, 12, 60, 12, 60, -12, 46.2)

time.sleep(delay)

leg_control(-11, 46, 11, 60, 11, 60, -11, 46)

time.sleep(delay)

leg_control(-10, 45.8, 10, 60, 10, 60, -10, 45.8)

time.sleep(delay)

leg_control(-9, 45.7, 9, 60, 9, 60, -9, 45.7)

time.sleep(delay)

leg_control(-8, 45.5, 8, 60, 8, 60, -8, 45.5)

time.sleep(delay)

leg_control(-7, 45.4, 7, 60, 7, 60, -7, 45.4)

time.sleep(delay)

leg_control(-6, 45.3, 6, 60, 6, 60, -6, 45.3)

time.sleep(delay)

leg_control(-5, 45.2, 5, 60, 5, 60, -5, 45.2)

time.sleep(delay)

leg_control(-4, 45.1, 4, 60, 4, 60, -4, 45.1)

time.sleep(delay)

leg_control(-3, 45.1, 3, 60, 3, 60, -3, 45.1)

time.sleep(delay)

leg_control(-2, 45, 2, 60, 2, 60, -2, 45)

time.sleep(delay)

leg_control(-1, 45, 1, 60, 1, 60, -1, 45)

time.sleep(delay)

leg_control(0, 45, 0, 60, 0, 60, 0, 45)

time.sleep(delay)

leg_control(1, 45, -1, 60, -1, 60, 1, 45)

time.sleep(delay)

leg_control(2, 45, -2, 60, -2, 60, 2, 45)

time.sleep(delay)

leg_control(3, 45.1, -3, 60, -3, 60, 3, 45.1)

time.sleep(delay)

leg_control(4, 45.1, -4, 60, -4, 60, 4, 45.1)

time.sleep(delay)

leg_control(5, 45.2, -5, 60, -5, 60, 5, 45.2)

time.sleep(delay)

leg_control(6, 45.3, -6, 60, -6, 60, 6, 45.3)

time.sleep(delay)

leg_control(7, 45.4, -7, 60, -7, 60, 7, 45.4)

time.sleep(delay)

leg_control(8, 45.5, -8, 60, -8, 60, 8, 45.5)

time.sleep(delay)

leg_control(9, 45.7, -9, 60, -9, 60, 9, 45.7)

time.sleep(delay)

leg_control(10, 45.8, -10, 60, -10, 60, 10, 45.8)

time.sleep(delay)

leg_control(11, 46, -11, 60, -11, 60, 11, 46)

time.sleep(delay)

leg_control(12, 46.2, -12, 60, -12, 60, 12, 46.2)

time.sleep(delay)

leg_control(13, 46.4, -13, 60, -13, 60, 13, 46.4)

time.sleep(delay)

leg_control(14, 46.7, -14, 60, -14, 60, 14, 46.7)

time.sleep(delay)

leg_control(15, 46.9, -15, 60, -15, 60, 15, 46.9)

time.sleep(delay)

leg_control(16, 47.2, -16, 60, -16, 60, 16, 47.2)

time.sleep(delay)

leg_control(17, 47.5, -17, 60, -17, 60, 17, 47.5)

time.sleep(delay)

leg_control(18, 47.8, -18, 60, -18, 60, 18, 47.8)

time.sleep(delay)

leg_control(19, 48.1, -19, 60, -19, 60, 19, 48.1)

time.sleep(delay)

leg_control(20, 48.4, -20, 60, -20, 60, 20, 48.4)

time.sleep(delay)

leg_control(21, 48.8, -21, 60, -21, 60, 21, 48.8)

time.sleep(delay)

leg_control(22, 49.2, -22, 60, -22, 60, 22, 49.2)

time.sleep(delay)

leg_control(23, 49.6, -23, 60, -23, 60, 23, 49.6)

time.sleep(delay)

leg_control(24, 50, -24, 60, -24, 60, 24, 50)

time.sleep(delay)

leg_control(25, 50.5, -25, 60, -25, 60, 25, 50.5)

time.sleep(delay)

leg_control(26, 50.9, -26, 60, -26, 60, 26, 50.9)

time.sleep(delay)

leg_control(27, 51.4, -27, 60, -27, 60, 27, 51.4)

time.sleep(delay)

leg_control(28, 51.9, -28, 60, -28, 60, 28, 51.9)

time.sleep(delay)

leg_control(29, 52.5, -29, 60, -29, 60, 29, 52.5)

time.sleep(delay)

leg_control(30, 53, -30, 60, -30, 60, 30, 53)

time.sleep(delay)

leg_control(31, 53.6, -31, 60, -31, 60, 31, 53.6)

time.sleep(delay)

leg_control(32, 54.2, -32, 60, -32, 60, 32, 54.2)

time.sleep(delay)

leg_control(33, 54.9, -33, 60, -33, 60, 33, 54.9)

time.sleep(delay)

leg_control(34, 55.6, -34, 60, -34, 60, 34, 55.6)

time.sleep(delay)

leg_control(35, 56.3, -35, 60, -35, 60, 35, 56.3)

time.sleep(delay)

leg_control(36, 57, -36, 60, -36, 60, 36, 57)

time.sleep(delay)

leg_control(37, 57.8, -37, 60, -37, 60, 37, 57.8)

time.sleep(delay)

leg_control(38, 58.6, -38, 60, -38, 60, 38, 58.6)

time.sleep(delay)

leg_control(39, 59.4, -39, 60, -39, 60, 39, 59.4)

time.sleep(delay)

leg_control(40, 60, -40, 60, -40, 60, 40, 60)

time.sleep(delay)

# half way point

leg_control(40, 60, -40, 60, -40, 60, 40, 60)

time.sleep(delay)

leg_control(39, 60, -39, 59.4, -39, 59.4, 39, 60)

time.sleep(delay)

leg_control(38, 60, -38, 58.6, -38, 58.6, 38, 60)

time.sleep(delay)

leg_control(37, 60, -37, 57.8, -37, 57.8, 37, 60)

time.sleep(delay)

leg_control(36, 60, -36, 57, -36, 57, 36, 60)

time.sleep(delay)

leg_control(35, 60, -35, 56.3, -35, 56.3, 35, 60)

time.sleep(delay)

leg_control(34, 60, -34, 55.6, -34, 55.6, 34, 60)

time.sleep(delay)

leg_control(33, 60, -33, 54.9, -33, 54.9, 33, 60)

time.sleep(delay)

leg_control(32, 60, -32, 54.2, -32, 54.2, 32, 60)

time.sleep(delay)

leg_control(31, 60, -31, 53.6, -31, 53.6, 31, 60)

time.sleep(delay)

leg_control(30, 60, -30, 53, -30, 53, 30, 60)

time.sleep(delay)

leg_control(29, 60, -29, 52.5, -29, 52.5, 29, 60)

time.sleep(delay)

leg_control(28, 60, -28, 51.9, -28, 51.9, 28, 60)

time.sleep(delay)

leg_control(27, 60, -27, 51.4, -27, 51.4, 27, 60)

time.sleep(delay)

leg_control(26, 60, -26, 50.9, -26, 50.9, 26, 60)

time.sleep(delay)

leg_control(25, 60, -25, 50.5, -25, 50.5, 25, 60)

time.sleep(delay)

leg_control(24, 60, -24, 50, -24, 50, 24, 60)

time.sleep(delay)

leg_control(23, 60, -23, 49.6, -23, 49.6, 23, 60)

time.sleep(delay)

leg_control(22, 60, -22, 49.2, -22, 49.2, 22, 60)

time.sleep(delay)

leg_control(21, 60, -21, 48.8, -21, 48.8, 21, 60)

time.sleep(delay)

leg_control(20, 60, -20, 48.4, -20, 48.4, 20, 60)

time.sleep(delay)

leg_control(19, 60, -19, 48.1, -19, 48.1, 19, 60)

time.sleep(delay)

leg_control(18, 60, -18, 47.8, -18, 47.8, 18, 60)

time.sleep(delay)

leg_control(17, 60, -17, 47.5, -17, 47.5, 17, 60)

time.sleep(delay)

leg_control(16, 60, -16, 47.2, -16, 47.2, 16, 60)

time.sleep(delay)

leg_control(15, 60, -15, 46.9, -15, 46.9, 15, 60)

time.sleep(delay)

leg_control(14, 60, -14, 46.7, -14, 46.7, 14, 60)

time.sleep(delay)

leg_control(13, 60, -13, 46.4, -13, 46.4, 13, 60)

time.sleep(delay)

leg_control(12, 60, -12, 46.2, -12, 46.2, 12, 60)

time.sleep(delay)

leg_control(11, 60, -11, 46, -11, 46, 11, 60)

time.sleep(delay)

leg_control(10, 60, -10, 45.8, -10, 45.8, 10, 60)

time.sleep(delay)

leg_control(9, 60, -9, 45.7, -9, 45.7, 9, 60)

time.sleep(delay)

leg_control(8, 60, -8, 45.5, -8, 45.5, 8, 60)

time.sleep(delay)

leg_control(7, 60, -7, 45.4, -7, 45.4, 7, 60)

time.sleep(delay)

leg_control(6, 60, -6, 45.3, -6, 45.3, 6, 60)

time.sleep(delay)

leg_control(5, 60, -5, 45.2, -5, 45.2, 5, 60)

time.sleep(delay)

leg_control(4, 60, -4, 45.1, -4, 45.1, 4, 60)

time.sleep(delay)

leg_control(3, 60, -3, 45.1, -3, 45.1, 3, 60)

time.sleep(delay)

leg_control(2, 60, -2, 45, -2, 45, 2, 60)

time.sleep(delay)

leg_control(1, 60, -1, 45, -1, 45, 1, 60)

time.sleep(delay)

leg_control(0, 60, 0, 45, 0, 45, 0, 60)

time.sleep(delay)

leg_control(-1, 60, 1, 45, 1, 45, -1, 60)

time.sleep(delay)

leg_control(-2, 60, 2, 45, 2, 45, -2, 60)

time.sleep(delay)

leg_control(-3, 60, 3, 45.1, 3, 45.1, -3, 60)

time.sleep(delay)

leg_control(-4, 60, 4, 45.1, 4, 45.1, -4, 60)

time.sleep(delay)

leg_control(-5, 60, 5, 45.2, 5, 45.2, -5, 60)

time.sleep(delay)

leg_control(-6, 60, 6, 45.3, 6, 45.3, -6, 60)

time.sleep(delay)

leg_control(-7, 60, 7, 45.4, 7, 45.4, -7, 60)

time.sleep(delay)

leg_control(-8, 60, 8, 45.5, 8, 45.5, -8, 60)

time.sleep(delay)

leg_control(-9, 60, 9, 45.7, 9, 45.7, -9, 60)

time.sleep(delay)

leg_control(-10, 60, 10, 45.8, 10, 45.8, -10, 60)

time.sleep(delay)

leg_control(-11, 60, 11, 46, 11, 46, -11, 60)

time.sleep(delay)

leg_control(-12, 60, 12, 46.2, 12, 46.2, -12, 60)

time.sleep(delay)

leg_control(-13, 60, 13, 46.4, 13, 46.4, -13, 60)

time.sleep(delay)

leg_control(-14, 60, 14, 46.7, 14, 46.7, -14, 60)

time.sleep(delay)

leg_control(-15, 60, 15, 46.9, 15, 46.9, -15, 60)

time.sleep(delay)

leg_control(-16, 60, 16, 47.2, 16, 47.2, -16, 60)

time.sleep(delay)

leg_control(-17, 60, 17, 47.5, 17, 47.5, -17, 60)

time.sleep(delay)

leg_control(-18, 60, 18, 47.8, 18, 47.8, -18, 60)

time.sleep(delay)

leg_control(-19, 60, 19, 48.1, 19, 48.1, -19, 60)

time.sleep(delay)

leg_control(-20, 60, 20, 48.4, 20, 48.4, -20, 60)

time.sleep(delay)

leg_control(-21, 60, 21, 48.8, 21, 48.8, -21, 60)

time.sleep(delay)

leg_control(-22, 60, 22, 49.2, 22, 49.2, -22, 60)

time.sleep(delay)

leg_control(-23, 60, 23, 49.6, 23, 49.6, -23, 60)

time.sleep(delay)

leg_control(-24, 60, 24, 50, 24, 50, -24, 60)

time.sleep(delay)

leg_control(-25, 60, 25, 50.5, 25, 50.5, -25, 60)

time.sleep(delay)

leg_control(-26, 60, 26, 50.9, 26, 50.9, -26, 60)

time.sleep(delay)

leg_control(-27, 60, 27, 51.4, 27, 51.4, -27, 60)

time.sleep(delay)

leg_control(-28, 60, 28, 51.9, 28, 51.9, -28, 60)

time.sleep(delay)

leg_control(-29, 60, 29, 52.5, 29, 52.5, -29, 60)

time.sleep(delay)

leg_control(-30, 60, 30, 53, 30, 53, -30, 60)

time.sleep(delay)

leg_control(-31, 60, 31, 53.6, 31, 53.6, -31, 60)

time.sleep(delay)

leg_control(-32, 60, 32, 54.2, 32, 54.2, -32, 60)

time.sleep(delay)

leg_control(-33, 60, 33, 54.9, 33, 54.9, -33, 60)

time.sleep(delay)

leg_control(-34, 60, 34, 55.6, 34, 55.6, -34, 60)

time.sleep(delay)

leg_control(-35, 60, 35, 56.3, 35, 56.3, -35, 60)

time.sleep(delay)

leg_control(-36, 60, 36, 57, 36, 57, -36, 60)

time.sleep(delay)

leg_control(-37, 60, 37, 57.8, 37, 57.8, -37, 60)

time.sleep(delay)

leg_control(-38, 60, 38, 58.6, 38, 58.6, -38, 60)

time.sleep(delay)

leg_control(-39, 60, 39, 59.4, 39, 59.4, -39, 60)

time.sleep(delay)

leg_control(-40, 60, 40, 60, 40, 60, -40, 60)

time.sleep(delay)